package com.nenmei.source.config;

import ch.qos.logback.core.db.DBHelper;
import com.nenmei.source.bean.Car;
import com.nenmei.source.bean.Employee;
import com.nenmei.source.bean.Pet;
import com.nenmei.source.bean.User;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.*;

/**
 * @date: 2021/08/06
 * @time: 17:11
 * @author: yuyifan
 *
 * 1,配置累里面使用@Bean标注在方法上给容器注册组件,默认也是单实例的
 * 2,配置类本身(MyConfig.class)也是组件
 * 3,proxyBeanMethods: 代理bean的方法, 默认为true
 *   Full(proxyBeanMethods = true),
 *   Lite(proxyBeanMethods = false),
 *   体现在组件依赖中; 为true时组件相互依赖,为false时组件相互不依赖;
 *   建议proxyBeanMethods = false,不需要检查相互依赖的组件
 *
 * 4,@Import({User.class, DBHelper.class}):
 *   导入组件; 给容器中自动创建出这两个类型的组件,默认组件的名字就是全类名(比如com.nenmei.source.bean.User),
 *   和我们自己手动写的user01不是同一个组件
 *
 *   5,@ImportResource("classpath:bean.xml")"
 *   原生配置文件引入,不过一般不用;
 *
 * 6,@EnableConfigurationProperties(Car.class)
 *   第一个作用是开启Car配置绑定功能
 *   第二个作用是把Car这个组件自动注册到容器中,相比较于用@Component这种方法,该方法比如在引入外来包时候效果更好
 */
@Import({User.class, DBHelper.class})
@Configuration(proxyBeanMethods = true) //告诉SpringBoot这是一个配置类 == 配置文件
//@ConditionalOnBean(name = "kitty")
@ImportResource("classpath:bean.xml")
@EnableConfigurationProperties(Car.class)
public class MyConfig {
    /**
     *
     * proxyBeanMethods = true的时候,
     * 外部无论对配置类中的这个组件调用多少次,获取的都是之前注册容器中的单实例对象;
     * User user = bean.user01();
     * User user1 = bean.user01();
     * System.out.println(user == user1);  结果为true
     *
     * proxyBeanMethods = false的时候,则反之
     * User user = bean.user01();
     * User user1 = bean.user01();
     * System.out.println(user == user1);  结果为false
     * @return
     */
    @Bean //给容器中添加组件,以方法名作为组件id,返回类型就是组件类型,返回的值,就是组件在容器中实例
    public User user01() {
        User user = new User("xiaolei", 23);
        // proxyBeanMethods = true时,User组件依赖了Pet组件,
        // proxyBeanMethods = false时,User组件不依赖Pet组件;
        user.setPet(tomPet());
        return user;
    }

    @Bean
    public Pet tomPet() {
        return new Pet("汤姆");
    }


    /**
     * 想要下面的employee01组件生效,这个king组件顺序必须在前面,写在其否则不生效
     * @return
     */
    @Bean(name = "king")
    public Pet kitty() {
        return new Pet("凯蒂");
    }

    /**
     * @ConditionalOnBean(name = "kitty"): 当容器中有ketty这个组件的时候我们才能干某些事
     * @ConditionalOnMissingBean(name = "xxx"): 当容器中没有xxx这个组件的时候我们才能干某些事
     *
     * @ConditionalOnClass
     * @ConditionalOnMissingClass
     *
     * @ConditionalOnWebApplication: 当是web应用的时候可以干
     * @ConditionalOnNotWebApplication
     *
     * @ConditionalOnResource
     * @return
     */
    @Bean
    @ConditionalOnBean(name = "king")
    public Employee employee01() {
        Employee employee = new Employee("小蕾", 23);
        employee.setPet(kitty());
        return employee;
    }



}
